package com.link2room.rodimus.facade.listener.receiver;

import com.link2room.common.constant.DefaultValue;
import com.link2room.common.service.ICommonService;
import com.link2room.common.util.JacksonUtil;
import com.link2room.common.util.StringUtil;
import com.link2room.rodimus.constant.MallGoodsConstant;
import com.link2room.rodimus.constant.MallOrderConstant;
import com.link2room.rodimus.dto.param.inside.MemberPackageInsideParamDto;
import com.link2room.rodimus.dto.result.base.MallGoodBaseExtraPMSCouponDto;
import com.link2room.rodimus.dto.result.base.MallGoodBaseExtraPMSPackageDto;
import com.link2room.rodimus.entity.MallGoodBase;
import com.link2room.rodimus.entity.MallOrderBase;
import com.link2room.rodimus.entity.MallOrderOptStaEntity;
import com.link2room.rodimus.entity.MallOrderPrice;
import com.link2room.rodimus.feign.soundwave.PmsMemberFeignService;
import com.link2room.rodimus.feign.trailbreaker.RefundFeignService;
import com.link2room.rodimus.listener.event.MallOrderPaySuccessEvent;
import com.link2room.rodimus.service.IMemberService;
import com.link2room.soundwave.constant.L2RCouponConstant;
import com.link2room.soundwave.constant.L2RPointConstant;
import com.link2room.soundwave.dto.param.inside.MemberUpgradeInsideParamDto;
import com.link2room.soundwave.dto.param.inside.PointPresentUseInsideParamDto;
import com.link2room.soundwave.dto.param.inside.UsableCouopnsInsideParamDto;
import com.link2room.trailbreaker.dto.param.RefundParamDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;

/**
 * 商城支付成功后做的事情
 * Created by LN on 2018/1/23
 */
@Component
public class MallOrderPaySuccessEventReceiver {
    @Resource
    private ICommonService commonService;
    @Autowired
    private PmsMemberFeignService pmsMemberFeignService;
    @Autowired
    private RefundFeignService refundFeignService;

    @EventListener(value = MallOrderPaySuccessEvent.class)
    @Async
    public void afterPaySuccessDo(MallOrderPaySuccessEvent paySuccessEvent) throws Exception {
        String orderNo = paySuccessEvent.getOrderNo();
        String lhotelGroupCode = paySuccessEvent.getLhotelGroupCode();
        MallOrderBase findOrder = new MallOrderBase();
        findOrder.setLhotelGroupCode(lhotelGroupCode);
        findOrder.setOrderCode(orderNo);
        MallOrderBase mallOrder = commonService.findOnlyOneEQ(MallOrderBase.class, findOrder);
        if (null == mallOrder) {
            return;
        }
        //订单是否成功,做后续操作
        if (!MallOrderConstant.Sta.init.equals(mallOrder.getSta())) {
            return;
        } else {
            if (MallGoodsConstant.GoodType.PMSCARD.equals(mallOrder.getGoodType())) {
                pmsCardHandler(mallOrder);
            } else if (MallGoodsConstant.GoodType.PMSCOUPON.equals(mallOrder.getGoodType())) {
                try {
                    pmsCouponHandler(mallOrder);
                }catch (Exception e){
                    fallBack(mallOrder);
                    throw e;
                }
            } else if (MallGoodsConstant.GoodType.PMSPACKAGE.equals(mallOrder.getGoodType())){
                pmsPackageHandler(mallOrder);
            }
        }
    }

    private void pmsPackageHandler(MallOrderBase mallOrder) throws Exception {
        String orderCode = mallOrder.getOrderCode();
        String lhotelGroupCode = mallOrder.getLhotelGroupCode();
        MallOrderPrice find = new MallOrderPrice();
        find.setLhotelGroupCode(lhotelGroupCode);
        find.setOrderCode(orderCode);
        MallOrderPrice mallOrderPrice = commonService.findOneEQ(MallOrderPrice.class, find);
        String goodCode = mallOrderPrice.getGoodCode();
        MallGoodBase goodBase = findMallGoodBase(lhotelGroupCode, goodCode);
        String extra = goodBase.getGoodExtra();
        MallGoodBaseExtraPMSPackageDto pmsPackageDto = JacksonUtil.jsonToBean(extra, MallGoodBaseExtraPMSPackageDto.class);
        String activityCode = pmsPackageDto.getActivityCode();
        MemberPackageInsideParamDto insideParamDto = new MemberPackageInsideParamDto();
        insideParamDto.setLhotelGroupCode(lhotelGroupCode);
        insideParamDto.setL2rMemberNo(mallOrder.getMemberNo());
        insideParamDto.setOrderNo(orderCode);
        insideParamDto.setActivityCode(activityCode);
        insideParamDto.setExchangeType(pmsPackageDto.getExchangeType());
        insideParamDto.setAmountValue(pmsPackageDto.getAmountValue());
        insideParamDto.setPointValue(pmsPackageDto.getPointValue());
        pmsMemberFeignService.exchangePackage(insideParamDto);
    }


    private void fallBack(MallOrderBase mallOrder) throws Exception {
        if (StringUtil.isBlank(mallOrder.getOrderCode())) {
            return;
        }

        mallOrder.setSta(MallOrderConstant.Sta.ERR_AUTO_CANCEL);
        MallOrderOptStaEntity fallbackSoundPayEntity  = MallOrderOptStaEntity.createSoundwavePayStaEntity(mallOrder.getLhotelGroupCode(), mallOrder.getOrderCode());
        //退积分
        try {
            addPMSPoint(mallOrder.getMemberNo(),mallOrder.getPoint(),"",mallOrder.getGoodType());
        }catch (Exception e){
            fallbackSoundPayEntity.setOperSta(MallOrderConstant.ORDER_OPT.STA.F);
            throw e;
        }finally {
            commonService.save(fallbackSoundPayEntity);
        }

        //退钱
        MallOrderOptStaEntity fallbackTreailStaEntity = MallOrderOptStaEntity.fallbackTrailbreakerStaEntity(mallOrder.getLhotelGroupCode(), mallOrder.getOrderCode());
        try {
            //卡升级失败,退款
            RefundParamDto paramDto = new RefundParamDto();
            paramDto.setLhotelGroupCode(mallOrder.getLhotelGroupCode());
            paramDto.setOrderNo(mallOrder.getOrderCode());
            paramDto.setIsFullyRefund(DefaultValue.T);
            refundFeignService.refund(paramDto);
        } catch (Exception ee) {
            fallbackTreailStaEntity.setOperSta(MallOrderConstant.ORDER_OPT.STA.F);
            throw ee;
        } finally {
            commonService.save(fallbackTreailStaEntity);
            commonService.merge(mallOrder);
        }


    }

    private void addPMSPoint(String l2rMemberNo , BigDecimal point,String remark,String goodType ) throws Exception {
        if(StringUtil.isBlank(l2rMemberNo)){
            return;
        }
        PointPresentUseInsideParamDto pointPresentUseInsideParamDto = new PointPresentUseInsideParamDto();
        pointPresentUseInsideParamDto.setL2rMemberNo(l2rMemberNo);
        pointPresentUseInsideParamDto.setRemark(remark);
        pointPresentUseInsideParamDto.setPoint(point);
        pointPresentUseInsideParamDto.setSrcType(L2RPointConstant.SRC_TYPE.MALL);
        if(MallGoodsConstant.GoodType.PMSPACKAGE.equals(goodType)){
            pointPresentUseInsideParamDto.setGoodType(L2RPointConstant.GOOD_TYPE.PMSPACKAGE);
        }
        pmsMemberFeignService.addPoint(pointPresentUseInsideParamDto);
    }
    private void pmsCouponHandler(MallOrderBase mallOrder) throws Exception {

        String orderCode = mallOrder.getOrderCode();
        String lhotelGroupCode = mallOrder.getLhotelGroupCode();
        MallOrderPrice find = new MallOrderPrice();
        find.setLhotelGroupCode(lhotelGroupCode);
        find.setOrderCode(orderCode);
        MallOrderPrice mallOrderPrice = commonService.findOneEQ(MallOrderPrice.class, find);
        String goodCode = mallOrderPrice.getGoodCode();
        MallGoodBase mallGoodBase = findMallGoodBase(lhotelGroupCode,goodCode);
        String extra = mallGoodBase.getGoodExtra();
        MallGoodBaseExtraPMSCouponDto pmscoupon = JacksonUtil.jsonToBean(extra, MallGoodBaseExtraPMSCouponDto.class);

        UsableCouopnsInsideParamDto paramDto = new UsableCouopnsInsideParamDto();
        paramDto.setL2RMemberNo(mallOrder.getMemberNo());
        paramDto.setPmsCouponCode(pmscoupon.getCouponCode());
        paramDto.setSaleNum(1);
        paramDto.setSaleType(L2RCouponConstant.SALE_TYPE.POINT);
        pmsMemberFeignService.saleCouponsNew(paramDto);
    }
    private MallGoodBase findMallGoodBase(String lhotelGroupCode , String goodCode) throws Exception {
        MallGoodBase findGoodBase = new MallGoodBase();
        findGoodBase.setLhotelGroupCode(lhotelGroupCode);
        findGoodBase.setGoodCode(goodCode);
        return commonService.findOneEQ(MallGoodBase.class, findGoodBase);
    }
    private void pmsCardHandler(MallOrderBase mallOrder) throws Exception {
        String lhotelGroupCode = mallOrder.getLhotelGroupCode();
        String orderNo = mallOrder.getOrderCode();
        MallOrderOptStaEntity soundCreate = MallOrderOptStaEntity.createSoundwaveBusssStaEntity(lhotelGroupCode, orderNo);
        try {
            this.pmsCardUpgrade(lhotelGroupCode, mallOrder.getMemberNo(), mallOrder.getPrice());
        } catch (Exception e) {

            mallOrder.setSta(MallOrderConstant.Sta.ERR_AUTO_CANCEL);
            e.printStackTrace();
            soundCreate.setOperSta(MallOrderConstant.ORDER_OPT.STA.F);
            MallOrderOptStaEntity fallbackTreailStaEntity = MallOrderOptStaEntity.fallbackTrailbreakerStaEntity(lhotelGroupCode, orderNo);
            try {
                //卡升级失败,退款
                RefundParamDto paramDto = new RefundParamDto();
                paramDto.setLhotelGroupCode(mallOrder.getLhotelGroupCode());
                paramDto.setOrderNo(orderNo);
                paramDto.setIsFullyRefund(DefaultValue.T);
                refundFeignService.refund(paramDto);
            } catch (Exception ee) {
                fallbackTreailStaEntity.setOperSta(MallOrderConstant.ORDER_OPT.STA.F);
                throw ee;
            } finally {
                commonService.save(fallbackTreailStaEntity);
                commonService.merge(mallOrder);
            }
            throw e;
        } finally {
            commonService.save(soundCreate);
        }
    }

    private void pmsCardUpgrade(String lhotelGroupCode, String memberNo, BigDecimal price) {
        MemberUpgradeInsideParamDto paramDto = new MemberUpgradeInsideParamDto();
        paramDto.setLhotelGroupCode(lhotelGroupCode);
        paramDto.setL2RMemberNo(memberNo);
        paramDto.setAmount(price);
        pmsMemberFeignService.upgradeMmeber(paramDto);
    }
}


